package network

import (
	"encoding/binary"
	"fmt"
	"io"
)

func (m *TCPSocket) GetGuid() int64 {
	return m.guid
}

func (m *TCPSocket) Close() {
	m.tCPConn.Close()
}

func (r *TCPSocket) RemoteAddr() string {
	if r.tCPConn != nil {
		return r.tCPConn.RemoteAddr().String()
	}
	return ""
}

// 不可发送空数据 将会断开连接
func (m *TCPSocket) SendData(pack *SendPacket) bool {
	if pack == nil || len(pack.Data) == 0 {
		return false
	}
	select {
	case m.writeChan <- pack:
		return true
	default:
		//fmt.Printf("TCPSocket:%v SendData full!\n", m.GetGuid())
	}
	return false
}

func (m *TCPSocket) addPack(pt byte, p *RecvPacketType) {
	if p == nil {
		p = GetRecvPack(0)
	}
	p.Ptype = pt
	p.Guid = m.GetGuid()
	p.Addr = m.RemoteAddr()
	readChan <- p //PacketType{Ptype: pt, Guid: m.GetGuid(), Buf: b, Addr: m.RemoteAddr()}
}

func (m *TCPSocket) read() {
	defer func() {
		m.writeChan <- nil
		m.syncClose.Done()
		fmt.Printf("TCPSocket:%v read exit\n", m.GetGuid())
	}()

	headbuf := make([]byte, ID_TCPHEADER_LENGTH)
	dataLen := uint32(0)
	for {
		// 读取消息长度
		_, err := io.ReadFull(m.tCPConn, headbuf)
		if err != nil {
			if err != io.EOF {
				fmt.Printf("TCPSocket:%v recv data err:%v\n", m.GetGuid(), err)
			}
			break
		}

		dataLen = binary.BigEndian.Uint32(headbuf)
		if dataLen > ID_DATA_MAX_LENGTH || dataLen == 0 {
			fmt.Printf("TCPSocket:%v recv data length error %v\n", m.GetGuid(), dataLen)
			break
		}

		p := GetRecvPack(int(dataLen))

		_, err1 := io.ReadFull(m.tCPConn, p.Data)
		if err1 != nil {
			fmt.Printf("TCPSocket:%v recv data err:%v\n", m.GetGuid(), err1)
			break
		}

		m.addPack(ID_MSG_TYPE_RECV, p)
	}
}

func (m *TCPSocket) write() {
	defer func() {
		m.syncClose.Done()
		m.tCPConn.Close()
		fmt.Printf("TCPSocket:%v write exit\n", m.GetGuid())
	}()

	srcLenBuf := make([]byte, ID_TCPHEADER_LENGTH)
	var dataLen uint32

	for pack := range m.writeChan {
		if pack == nil {
			fmt.Printf("TCPSocket:%v write pack nil\n", m.GetGuid())
			return
		}
		dataLen = uint32(len(pack.Data))
		if dataLen == 0 {
			fmt.Printf("TCPSocket:%v write data zero\n", m.GetGuid())
			return
		}
		// 发送包体长度
		lenBuf := srcLenBuf
		binary.BigEndian.PutUint32(lenBuf, dataLen)

		for {
			n, err := m.tCPConn.Write(lenBuf)
			if err != nil {
				fmt.Printf("TCPSocket:%v write data err:%v\n", m.GetGuid(), err)
				return
			}

			if n <= 0 {
				continue
			}

			if n >= len(lenBuf) {
				break
			}
			lenBuf = lenBuf[n:]
		}

		data := pack.Data
		// 发送包体
		for {
			n, err := m.tCPConn.Write(data)
			if err != nil {
				fmt.Printf("TCPSocket:%v write data err:%v\n", m.GetGuid(), err)
				return
			}

			if n <= 0 {
				continue
			}

			if n >= len(data) {
				break
			}

			data = data[n:]
		}

		DeallocateSendPacket(pack)
	}

}
